#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'wshu'
__version__ = '1.0'
"""
    ***********************************
    *  @filename : utils.py
    *  @Author : wshu
    *  @CodeDate : 2020/4/16 21:46
    *  @Software : PyCharm
    ***********************************
"""
import re
import socket
from urllib.parse import urlparse

# ipv4 地址
re_ipv4 = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')

RE_URL_PROTOCOL = re.compile(r'(http|https)://', re.I)


def parse_ips(ips):
    c_ips = []
    _ips = ''
    if isinstance(ips, str):
        _ips = ips.strip().split(',')
    elif isinstance(ips, list):
        _ips = ips

    for _ip in _ips:
        c_ips.extend(parse_ip(_ip))

    return c_ips


def parse_ip(ips):
    '''note: deal with such ips
        192.168.*.*
        192.168.1-10.*
        192.168.1.*
        192.168.1.1-10
    '''
    ret = []
    _3_ip_range = []
    _ips = [i.strip() for i in ips.split('.')]

    assert len(_ips) == 4

    if _ips[2] == '*':
        _3_ip_range = range(1, 255)
    elif '-' in _ips[2]:
        ip_range = _ips[2].split('-')
        _3_ip_range = range(int(ip_range[0]), int(ip_range[1]))

    if _3_ip_range:
        ret = ['.'.join([_ips[0], _ips[1], str(i), _ips[3]]) for i in _3_ip_range]
    else:
        ret.append('.'.join(_ips))

    return ret


def parse_full_ip_list(ips):
    '''note: deal with such ips
        192.168.1.*
        192.168.1.1-10
        192.168.1.1
    '''

    ret = []
    _4_ip_range = []
    _ips = [i.strip() for i in ips.split('.')]

    assert len(_ips) == 4

    if _ips[3] == '*':
        _4_ip_range = range(1, 255)
    elif '-' in _ips[3]:
        ip_range = _ips[3].split('-')
        _4_ip_range = range(int(ip_range[0]), int(ip_range[1]))

    if _4_ip_range:
        ret = ['.'.join([_ips[0], _ips[1], _ips[2], str(i)]) for i in _4_ip_range]
    else:
        ret.append('.'.join(_ips))

    return ret


def get_ips_bydomain(domain):
    """ 通过域名来获得域名对应的IP列表
    #FIXME 由于程序性能限制和网络环境复杂，
    可能无法获取完整的IP列表
    """
    ips = []
    try:
        addr_info = socket.gethostbyname_ex(domain)
        ips.extend(addr_info[2])
    except socket.error:
        return ips
    for sub_domain in addr_info[1]:
        try:
            addr_info = socket.gethostbyname_ex(sub_domain)
            # FIXME addr_info aliaslist loop gethostbyname_ex
            ips.extend(addr_info[2])
        except socket.error:
            pass
    return list(set(ips))   # 尝试反复获取有重复IP，进行去重过滤

def get_ip_for_host(domain):
    """
    通过域名来获得域名对应的IP
    """
    host = urlparse(domain).netloc
    if not host:
        host = domain
    try:
        ip = socket.gethostbyname(host)
    except socket.gaierror:
        ip = '0.0.0.0'
    return ip

def domain_verify(ip, domain):
    """ 通过DNS解析判断这个IP 是否在域名的IP中
    # FIXME 如果有CDN存在， 这个函数可能导致正确有效结果被丢弃
    """
    ips = get_ips_bydomain(domain)
    if ip in ips:
        return True
    return False


def get_domain_byurl(url):
    """ 通过URL获取可能存在的域名, """
    par = urlparse(url)
    host = par.hostname
    if re_ipv4.match(host):
        return ''
    return host


def get_port_byurl(url):
    """ 通过URL获取可能存在的域名, """
    par = urlparse(url)
    if par.port is None:
        if url.startswith('https'):
            return '443'
        else:
            return '80'
    return par.port


def joinurl(ip, port, ignore=''):
    url = None
    if port == '443':
        url = 'https://%s' % ip
    elif port != ignore:
        url = "http://%s:%s" % (ip, port)
    return url


def addurlprot(domain):
    if not RE_URL_PROTOCOL.match(domain):
        return 'http://%s' % domain
    return domain


def is_lan_ip(ip_str):
    '''judge is lan ip or not

    @note: lan ip:
        10.0.0.0~10.255.255.255
        172.16.0.0~172.31.255.255
        192.168.0.0~192.168.255.255
    '''
    is_lan = False

    ips = ip_str.split('.')

    if ip_str.startswith('10.'):
        is_lan = True
    elif ip_str.startswith('192.168.'):
        is_lan = True
    elif ips[0] == '172' and 15 < int(ips[1]) < 32:
        is_lan = True

    return is_lan


if __name__ == '__main__':
    # print parse_ips(['192.168.1.*', '192.168.*.*', '192.168.20-30.*'])
    print(get_ip_for_host("www.chbcnet.com"))
